// //1、结构体数组作为函数返回值的使用
// #include<stdio.h>
// //创建购置书的信息结构体
// struct BookList
// {
//     char name[30];
//     int number;
//     float price;//单价
//     float SumMoney;//总计
// };
// //两个函数
// //1、struct BookList* InputBookInfo(struct BookList *book);//返回的是结构体指针类型
// //2、void Print_Book_List();//打印函数
// float Total=0;//全局变量存储总计金额

// //用结构体指针类型作为返回值，传入的是地址，参数用指针
// struct BooKList* InputBookInfo( struct BookList *book)
// {
   
//      scanf("%s%d%f",&book->name,&book->number,&book->price);
//      Total+=book->number*book->price;
//     return book;
// } 

// void Print_Book_List(struct BookList book)
// {
//     book.SumMoney=book.number*book.price;
//     printf("%-24s%d\t%.2f\t%.2f\n",book.name,book.number,book.price,book.SumMoney);
// }
// int main()
// {
//     //创建结构体数组变量
//    struct BookList Book[4];
//     //输入信息
//     printf("请输入购置书的信息：书名  数量  单价\n");
//     for(int i=0;i<4;i++)
//     {
//         InputBookInfo(&(Book[i]));//调用购置书的信息输入函数
//     }
//     printf("----------------------------------------\n");
//     printf("购书清单：\n");
//     printf("书名\t\t\t数量\t单价\t合计\n");
//     for(int i=0;i<4;i++)
//     {
//         Print_Book_List(Book[i]);
//     }
//     printf("购书金额总计：%.2f\n",Total);
// }




// //2、共用体和结构体内存
// #include<stdio.h>
// //创建结构体
// struct memb
// {
//     float f;
//     int i;
//     char c;
// };

// //创建共用体
// union Un
// {
//     float f1;
//     int n;
//     char c;
// };

// int main()
// {
//     //创建变量
//     struct memb st={0};
//     union Un un={0};
//     //求所占字节大小
//     printf("结构体：%zd\n",sizeof(st));
    
//     printf("共用体：%zd\n",sizeof(un));
//     return 0;
// }


// //3、共用体成员的初始化
// #include<stdio.h>
// //创建共用体
// union Un
// {
//     double de;
//     int num;
//     char c;
// };

// int main()
// {
//     //创建共用体变量
//     union Un tag;
//     tag.de=6.66;
//     tag.num=20;
//     tag.c='p';
//     printf("共用体成员的值：\n");
//     printf("tag.de=%lf\ntag.num=%d\ntag.c=%c\n",tag.de,tag.num,tag.c);
//     return 0;
// }


// //4、枚举的使用
// #include<stdio.h>
// //创建枚举
// enum Months
// {
//     //January,
//     January=1,
//     February,
//     March,
//     April,
//     May,
//     June,
//     July,
//     August,
//     September,
//     October,
//     November,
//     December
// };
// int main()
// {
//     //只有在定义枚举类型后，在可以创建枚举变量
//     enum Months month;//创建枚举变量
//     for(month=January;month<=December;month++)
//     {
//         printf("%2d  ",month);
//     }
//     return 0;
// }



//5、动态内存管理的函数的使用
//void* malloc (size_t size);
/*这个函数向内存申请⼀块连续可⽤的空间，并返回指向这块空间的指针。
• 如果开辟成功，则返回⼀个指向开辟好空间的指针。
• 如果开辟失败，则返回⼀个 NULL 指针，因此malloc的返回值⼀定要做检查。
• 返回值的类型是 void* ，所以malloc函数并不知道开辟空间的类型，具体在使⽤的时候使⽤者⾃
⼰来决定。
• 如果参数 size 为0，malloc的⾏为是标准是未定义的，取决于编译器。*/

// #include<stdio.h>
// #include<stdlib.h>
// int main()
// {
//     int* ptr=(int*)malloc(5*sizeof(int));//开辟5个整型数据空间
//     //判断
//     if(ptr==NULL)
//     {
//         perror("malloc");
//         return 1;
//     }
//     //申请成功
//     else
//     {
//         for(int i=0;i<5;i++)//此处注意开辟多少就是使用多少，越界使用操作是未定义的，可会导致程序崩溃、内存泄漏等。
//         {
//             *(ptr+i)=i+1;
//             printf("%d ",*(ptr+i));
//         }
//     }
//     //用完后释放开辟的空间
//     free(ptr);
//     ptr=NULL;
//     return 0;
// }


//6、
//void* calloc (size_t num, size_t size);
/*函数的功能是为 num 个⼤⼩为 size 的元素开辟⼀块空间，并且把空间的每个字节初始化为0。
• 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全
0。*/

// #include<stdio.h>
// #include<stdlib.h>
// int main()
// {
//     //和malloc()的对比
//     int* p1=(int*)malloc(5*sizeof(int));
//     int* p2=(int*)calloc(5,sizeof(int));
    
//     //对malloc()函数开辟的空间的判断
//     if(p1==NULL)
//     {
//         perror("malloc");
//         return 1;
//     }
//     else
//     {
//         for(int i=0;i<5;i++)
//         {
//             //此处在改变p1的时候，不能写为p1++，因为在后面用free()释放的时候，
//             //p1的地址已经改变了，会出现错误 ，此时free的就不是动态内存开的了，行为是未定义的
//            // *(p1+i)=i+1;
//             //一边输入一变输出
//             printf("%d ",*(p1+i));
//         }
//     }
//     printf("\n");

//     //对calloc()开辟空间的判断
//     if(p2==NULL)
//     {
//         perror("calloc");
//         return 1;
//     }
//     else
//     {
//         for(int i=0;i<5;i++)
//         {
//             //*(p2+i)=i+1;
//             printf("%d ",*(p2+i));
//         }
//     }
    
//     //释放,不能多次释放
//     free(p1);
//     p1=NULL;

//     free(p2);
//     p2=NULL;
//     return 0;
// }


// //7、
// //void* realloc (void* ptr, size_t size);
// /*那 realloc 函数就可以做到对动态开辟内存⼤
// ⼩的调整。
// • ptr 是要调整的内存地址
// • size 调整之后新⼤⼩
// • 返回值为调整之后的内存起始位置。
// • 这个函数调整原内存空间⼤⼩的基础上，还会将原来内存中的数据移动到 新 的空间。
// • realloc在调整内存空间的是存在两种情况：
// ◦ 情况1：原有空间之后有⾜够⼤的空间
// ◦ 情况2：原有空间之后没有⾜够⼤的空间*/

// #include<stdio.h>
// #include<stdlib.h>
// int main()
// {
//     int* ptr=(int*)malloc(5*sizeof(int));
//     if(ptr==NULL)
//     {
//         perror("malloc");
//         return 1;
//     }
//     else
//     {
//         for(int i=0;i<5;i++)
//         {
//             *(ptr+i)=i+1;
//             printf("%d ",*(ptr+i));
//         }
//     }
//     printf("\n");
//     //开辟的20个字节的空间，想扩大，会出现剩余空间不够，使用ralloc()时候
//     //会在堆区开辟新的一块空间，返回新的空间的首地址
//     int* ptr1=(int*)realloc(ptr,10*sizeof(int));//新的空间大小为40字节
//     //此处需要注意，不能直接写为ptr==(int*)realloc(ptr,10*sizeof(int));
//     //因为万一开辟失败，返回一个NULL,就会把原来的ptr里面的内容全部搞没，
//     //因为ptr被赋为了NULL
//     //所以先用一个新的指针接收，判断了再赋值
//     if(ptr1!=NULL)
//     {
//         //保证申请成功才赋值
//         ptr=ptr1;
//         for(int i=0;i<10;i++)
//         {
//             *(ptr+i)=i+1;
//             printf("%d ",*(ptr+i));
//         }
//         free(ptr);
//         ptr=NULL;
//     }
//     else
//     {
//         perror("ralloc");
//         //调整失败还是使用原来的空间
//        for(int i=0;i<5;i++)
//        {
//             *(ptr+i)=i+2;
//             printf("%d ",*(ptr+i));
//        }
//        free(ptr);
//        ptr=NULL;
//     }
//     return 0;
// }



//8、文件操作
/*使用所学文件操作，在当前目录下放一个文件data.txt，
写一个程序，将data.txt文件拷贝一份，生成data_copy.txt文件。
基本思路：
打开文件data.txt，读取数据
打开文件data_copy.txt，写数据
从data.txt中读取数据存放到data_copy.txt文件中，直到文件结束。
关闭两个文件*/

// #include<stdio.h>

// int main()
// {
//     FILE* pf=fopen("data.txt","r");
//     if(pf==NULL)
//     {
//         perror("fopen");
//         return 1; 
//     }

//     //单个写入和读取
//     //写入
//     // fputc('H',pf);
//     // fputc('e',pf);
//     // fputc('l',pf);
//     // fputc('l',pf);
//     // fputc('o',pf);

//     // char ch=0;
//     // for(ch='a';ch<='z';ch++)
//     // {
//     //     fputc(ch,pf);
//     // }

//     // //读文件
//     // char ch=0;
//     // while((ch=fgetc(pf))!=EOF)
//     // {
//     //     printf("%c ",ch);
//     // }


//     // //多个写入和读取
//     // fputs("Hello word!\n",pf);
//     // fputs("你好!\n",pf);
//     // fputs("Hello word!",pf);

//     //读取
//     char arr[10]={0};
//     printf("%s\n", fgets(arr,10,pf));

//     //关闭
//     fclose(pf);
//     pf=NULL;
//     return 0;
// }



/*9、使用所学文件操作，在当前目录下放一个文件data.txt，
写一个程序，将data.txt文件拷贝一份，生成data_copy.txt文件。
基本思路：
打开文件data.txt，读取数据
打开文件data_copy.txt，写数据
从data.txt中读取数据存放到data_copy.txt文件中，直到文件结束。
关闭两个文件*/
#include<stdio.h>

int main()
{
    FILE* pf=fopen("data.txt","r");
    if(pf==NULL)
    {
        perror("fopen read");
        return 1; 
    }

    FILE* pf1=fopen("data_copy.txt","w");
    if(pf1==NULL)
    {
        perror("fopen write");
        return 1;
    }

    char ch=0;
    while((ch=fgetc(pf))!=EOF)
    {
        fputc(ch,pf1);
    }
    fclose(pf1);
    pf1=NULL;
    fclose(pf);
    pf=NULL;
    return 0;
}